package com.reactim.message.config.validation;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.reactim.message.config.ReactimConfig;
import com.reactim.message.config.PerformanceTestConfig;

import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validator;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

/**
 * 配置健康检查器
 * 用于监控配置状态和健康检查
 */
@Component
@Slf4j
public class ConfigurationHealthChecker {
    
    @Autowired
    private ReactimConfig reactimConfig;
    
    @Autowired
    private PerformanceTestConfig performanceTestConfig;
    
    @Autowired
    private Validator validator;
    
    /**
     * 执行配置健康检查
     */
    public ConfigurationHealthResult performHealthCheck() {
        try {
            List<String> warnings = new ArrayList<>();
            List<String> errors = new ArrayList<>();
            
            // 检查ReactIM配置
            checkReactimConfig(warnings, errors);
            
            // 检查性能测试配置
            checkPerformanceTestConfig(warnings, errors);
            
            // 检查配置一致性
            checkConfigurationConsistency(warnings);
            
            ConfigurationHealthResult result = new ConfigurationHealthResult();
            result.setErrors(errors);
            result.setWarnings(warnings);
            result.setTimestamp(System.currentTimeMillis());
            
            if (!errors.isEmpty()) {
                result.setStatus("UNHEALTHY");
            } else if (!warnings.isEmpty()) {
                result.setStatus("WARNING");
            } else {
                result.setStatus("HEALTHY");
            }
            
            return result;
            
        } catch (Exception e) {
            log.error("配置健康检查失败", e);
            ConfigurationHealthResult result = new ConfigurationHealthResult();
            result.setStatus("ERROR");
            result.setErrors(List.of("配置健康检查失败: " + e.getMessage()));
            result.setTimestamp(System.currentTimeMillis());
            return result;
        }
    }
    
    /**
     * 检查ReactIM配置
     */
    private void checkReactimConfig(List<String> warnings, List<String> errors) {
        Set<ConstraintViolation<ReactimConfig>> violations = validator.validate(reactimConfig);
        for (ConstraintViolation<ReactimConfig> violation : violations) {
            errors.add(String.format("ReactIM配置错误 [%s]: %s", 
                violation.getPropertyPath(), violation.getMessage()));
        }
        
        // 检查连接配置的合理性
        ReactimConfig.ConnectionProperties connection = reactimConfig.getConnection();
        if (connection.getCleanupInterval() >= connection.getExpirationTime()) {
            warnings.add("清理任务执行间隔大于等于连接过期时间，可能导致连接无法及时清理");
        }
        
        // 检查监控配置
        ReactimConfig.ConnectionProperties.MonitoringProperties monitoring = connection.getMonitoring();
        if (monitoring.getHeartbeatIntervalMs() * 3 > monitoring.getInactivityThresholdMs()) {
            warnings.add("心跳检测间隔过长，可能导致不活跃连接检测不及时");
        }
        
        // 检查缓存配置
        ReactimConfig.ConnectionProperties.CacheProperties cache = connection.getCache();
        if (cache.isEnabled() && cache.getConnectionCacheMaxSize() < 1000) {
            warnings.add(String.format("连接缓存容量较小(%d), 在高并发场景下可能影响性能", 
                cache.getConnectionCacheMaxSize()));
        }
        
        // 检查安全配置
        ReactimConfig.ConnectionProperties.SecurityProperties security = connection.getSecurity();
        if (security.isEnableEncryption() && !org.springframework.util.StringUtils.hasText(security.getEncryptionKey())) {
            warnings.add("启用了数据加密但未设置加密密钥，将使用默认密钥（不推荐用于生产环境）");
        }
    }
    
    /**
     * 检查性能测试配置
     */
    private void checkPerformanceTestConfig(List<String> warnings, List<String> errors) {
        Set<ConstraintViolation<PerformanceTestConfig>> violations = validator.validate(performanceTestConfig);
        for (ConstraintViolation<PerformanceTestConfig> violation : violations) {
            errors.add(String.format("性能测试配置错误 [%s]: %s", 
                violation.getPropertyPath(), violation.getMessage()));
        }
        
        if (!performanceTestConfig.isValid()) {
            errors.add("性能测试配置无效，请检查所有必需的配置项");
        }
        
        // 检查测试配置的合理性
        if (performanceTestConfig.getMaxConnections() > 50000) {
            warnings.add("最大连接数设置过高，可能导致系统资源不足");
        }
        
        if (performanceTestConfig.getOperationTimeoutSeconds() < 10) {
            warnings.add("操作超时时间过短，可能导致测试不稳定");
        }
    }
    
    /**
     * 检查配置一致性
     */
    private void checkConfigurationConsistency(List<String> warnings) {
        // 检查性能测试配置与主配置的一致性
        ReactimConfig.PerformanceProperties.TestProperties mainTestConfig = 
            reactimConfig.getPerformance().getTest();
        
        if (performanceTestConfig.getMaxConnections() != mainTestConfig.getMaxConnections()) {
            warnings.add("性能测试配置中的最大连接数与主配置不一致");
        }
        
        if (performanceTestConfig.getOperationTimeoutSeconds() != mainTestConfig.getOperationTimeoutSeconds()) {
            warnings.add("性能测试配置中的操作超时时间与主配置不一致");
        }
    }
    
    /**
     * 获取配置健康状态摘要
     */
    public ConfigurationHealthSummary getHealthSummary() {
        ConfigurationHealthResult healthResult = performHealthCheck();
        Map<String, Object> details = new HashMap<>();
        details.put("errors", healthResult.getErrors());
        details.put("warnings", healthResult.getWarnings());
        details.put("timestamp", healthResult.getTimestamp());
        
        return new ConfigurationHealthSummary(
            healthResult.getStatus(),
            details
        );
    }
    
    /**
     * 配置健康检查结果
     */
    public static class ConfigurationHealthResult {
        private String status;
        private List<String> errors = new ArrayList<>();
        private List<String> warnings = new ArrayList<>();
        private long timestamp;
        
        public String getStatus() {
            return status;
        }
        
        public void setStatus(String status) {
            this.status = status;
        }
        
        public List<String> getErrors() {
            return errors;
        }
        
        public void setErrors(List<String> errors) {
            this.errors = errors;
        }
        
        public List<String> getWarnings() {
            return warnings;
        }
        
        public void setWarnings(List<String> warnings) {
            this.warnings = warnings;
        }
        
        public long getTimestamp() {
            return timestamp;
        }
        
        public void setTimestamp(long timestamp) {
            this.timestamp = timestamp;
        }
        
        public boolean hasErrors() {
            return errors != null && !errors.isEmpty();
        }
        
        public boolean hasWarnings() {
            return warnings != null && !warnings.isEmpty();
        }
    }
    
    /**
     * 配置健康状态摘要
     */
    public static class ConfigurationHealthSummary {
        private final String status;
        private final Object details;
        
        public ConfigurationHealthSummary(String status, Object details) {
            this.status = status;
            this.details = details;
        }
        
        public String getStatus() {
            return status;
        }
        
        public Object getDetails() {
            return details;
        }
    }
}